import React, { createContext, useContext, useState, ReactNode, useCallback } from 'react';
import { Button, Result, Modal, App } from 'antd';
import { ExclamationCircleOutlined, ReloadOutlined, HomeOutlined, BugOutlined } from '@ant-design/icons';

interface ErrorInfo {
  message: string;
  code?: string | number;
  details?: string;
  stack?: string;
  timestamp: Date;
  id: string;
}

interface ErrorContextType {
  errors: ErrorInfo[];
  showError: (error: string | Error, options?: ErrorOptions) => void;
  clearErrors: () => void;
  clearError: (id: string) => void;
  reportError: (error: ErrorInfo) => void;
}

interface ErrorOptions {
  toast?: boolean;
  modal?: boolean;
  code?: string | number;
  details?: string;
  onRetry?: () => void;
  retryText?: string;
}

const ErrorContext = createContext<ErrorContextType | undefined>(undefined);

export const useError = () => {
  const context = useContext(ErrorContext);
  if (!context) {
    throw new Error('useError must be used within an ErrorProvider');
  }
  return context;
};

interface ErrorProviderProps {
  children: ReactNode;
  onErrorReport?: (error: ErrorInfo) => void;
}

export const ErrorProvider: React.FC<ErrorProviderProps> = ({ 
  children, 
  onErrorReport 
}) => {
  const [errors, setErrors] = useState<ErrorInfo[]>([]);
  const [modalError, setModalError] = useState<ErrorInfo | null>(null);
  const { message } = App.useApp();

  const generateErrorId = () => {
    return `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  };

  const showError = useCallback((error: string | Error, options: ErrorOptions = {}) => {
    const errorInfo: ErrorInfo = {
      id: generateErrorId(),
      message: typeof error === 'string' ? error : error.message,
      code: options.code,
      details: options.details || (typeof error === 'object' ? error.stack : undefined),
      stack: typeof error === 'object' ? error.stack : undefined,
      timestamp: new Date()
    };

    setErrors(prev => [...prev, errorInfo]);

    // 显示 message 通知
    if (options.toast !== false) {
      message.error(errorInfo.message);
    }

    // 显示模态框
    if (options.modal) {
      setModalError(errorInfo);
    }

    // 报告错误
    if (onErrorReport) {
      onErrorReport(errorInfo);
    }
  }, [onErrorReport]);

  const clearErrors = useCallback(() => {
    setErrors([]);
  }, []);

  const clearError = useCallback((id: string) => {
    setErrors(prev => prev.filter(error => error.id !== id));
  }, []);

  const reportError = useCallback((error: ErrorInfo) => {
    if (onErrorReport) {
      onErrorReport(error);
    }
  }, [onErrorReport]);

  const handleModalClose = () => {
    setModalError(null);
  };

  const handleReload = () => {
    window.location.reload();
  };

  const handleGoHome = () => {
    window.location.href = '/';
  };

  const contextValue: ErrorContextType = {
    errors,
    showError,
    clearErrors,
    clearError,
    reportError
  };

  return (
    <ErrorContext.Provider value={contextValue}>
      {children}
      
      {/* 错误模态框 */}
      <Modal
        open={!!modalError}
        onCancel={handleModalClose}
        footer={[
          <Button key="home" icon={<HomeOutlined />} onClick={handleGoHome}>
            返回首页
          </Button>,
          <Button key="reload" icon={<ReloadOutlined />} onClick={handleReload}>
            刷新页面
          </Button>,
          <Button key="close" type="primary" onClick={handleModalClose}>
            关闭
          </Button>
        ]}
        title="系统错误"
        width={600}
      >
        {modalError && (
          <Result
            status="error"
            title={modalError.message}
            subTitle={modalError.details || '系统遇到了一个错误，请尝试刷新页面或联系技术支持'}
            extra={[
              modalError.code && (
                <p key="code" className="text-gray-500 text-sm">
                  错误代码: {modalError.code}
                </p>
              ),
              <p key="time" className="text-gray-400 text-xs">
                发生时间: {modalError.timestamp.toLocaleString()}
              </p>
            ]}
          />
        )}
      </Modal>
    </ErrorContext.Provider>
  );
};

// 错误边界组件
interface ErrorBoundaryProps {
  children: ReactNode;
  fallback?: ReactNode;
  onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
}

interface ErrorBoundaryState {
  hasError: boolean;
  error?: Error;
}

export class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
  constructor(props: ErrorBoundaryProps) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error: Error): ErrorBoundaryState {
    return { hasError: true, error };
  }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    console.error('ErrorBoundary caught an error:', error, errorInfo);
    
    if (this.props.onError) {
      this.props.onError(error, errorInfo);
    }
  }

  handleReload = () => {
    window.location.reload();
  };

  handleGoHome = () => {
    window.location.href = '/';
  };

  render() {
    if (this.state.hasError) {
      if (this.props.fallback) {
        return this.props.fallback;
      }

      return (
        <div className="min-h-screen flex items-center justify-center bg-gray-50">
          <Result
            status="error"
            title="页面出现错误"
            subTitle="抱歉，页面遇到了一个错误。请尝试刷新页面或返回首页。"
            extra={[
              <Button 
                key="home" 
                icon={<HomeOutlined />} 
                onClick={this.handleGoHome}
              >
                返回首页
              </Button>,
              <Button 
                key="reload" 
                type="primary" 
                icon={<ReloadOutlined />} 
                onClick={this.handleReload}
              >
                刷新页面
              </Button>
            ]}
          >
            {this.state.error && (
              <details className="mt-4 text-left">
                <summary className="cursor-pointer text-gray-600 hover:text-gray-800">
                  <BugOutlined className="mr-2" />
                  查看错误详情
                </summary>
                <pre className="mt-2 p-4 bg-gray-100 rounded text-xs overflow-auto max-h-40">
                  {this.state.error.stack}
                </pre>
              </details>
            )}
          </Result>
        </div>
      );
    }

    return this.props.children;
  }
}

// 便捷的 Hook 用于处理 API 错误
export const useApiError = () => {
  const { showError } = useError();

  const handleApiError = useCallback((error: any, options?: {
    showMessage?: boolean;
    showModal?: boolean;
    onRetry?: () => void;
  }) => {
    let message = '网络请求失败';
    let code: string | number | undefined;
    let details: string | undefined;

    if (error?.response) {
      // HTTP 错误响应
      code = error.response.status;
      message = error.response.data?.message || `HTTP ${code} 错误`;
      details = error.response.data?.details;
    } else if (error?.request) {
      // 网络错误
      message = '网络连接失败，请检查网络设置';
      code = 'NETWORK_ERROR';
    } else if (error?.message) {
      // 其他错误
      message = error.message;
    }

    showError(message, {
      code,
      details,
      toast: options?.showMessage !== false,
      modal: options?.showModal,
      onRetry: options?.onRetry
    });
  }, [showError]);

  return { handleApiError };
};

export default ErrorProvider;